package cn.vonce.validator.intercept;

import cn.vonce.validator.annotation.VBean;
import cn.vonce.validator.config.EnableValidator;
import cn.vonce.validator.config.ResultConfig;
import cn.vonce.validator.enumerate.ResultCode;
import cn.vonce.validator.enumerate.ResultType;
import cn.vonce.validator.exception.ValidatorException;
import cn.vonce.validator.helper.ValidatorHelper;
import cn.vonce.validator.model.BeanResult;
import cn.vonce.validator.model.FieldResult;
import cn.vonce.validator.utils.RequestDataUtil;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.logging.Logger;

/**
 * 校验字段拦截器
 *
 * @author Jovi
 * @version 1.0
 * @email imjovi@qq.com
 * @date 2017年4月20日下午23:56:08
 */
public class ValidatorInterceptor implements MethodInterceptor {

    private final Logger logger = Logger.getLogger(this.getClass().getName());

    @Override
    public Object invoke(MethodInvocation arg0) throws Throwable {
        String fullName = arg0.getMethod().getReturnType().getSimpleName() + " " + arg0.getThis().getClass().getName() + "." + arg0.getMethod().getName();
        if (fullName.contains("$$")) {
            return arg0.proceed();
        }
        if (arg0.getArguments().length == 0) {
            return arg0.proceed();
        }
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
        BeanResult beanResult = new BeanResult(true, "校验通过");
        for (int i = 0; i < arg0.getArguments().length; i++) {
            // 获取实际对象-即为原始对象(可能是Bean，也可能是字段)
            Object object = arg0.getArguments()[i];
            Annotation[] annotations = arg0.getMethod().getParameterAnnotations()[i];
            // 优先校验bean
            VBean validBean = ValidatorHelper.getAnnotation(annotations, VBean.class);
            if (validBean != null) {
                beanResult = ValidatorHelper.validBean(object, validBean.group(), validBean.interrupt());
                break;
            }
            // 校验有注解的字段
            List<FieldResult> validFieldResultList = ValidatorHelper.valid(annotations, arg0.getMethod().getName() + "方法第" + (i + 1) + "个参数", object, null, "", true);
            if (!validFieldResultList.isEmpty()) {
                beanResult = new BeanResult("校验存在" + validFieldResultList.size() + "条错误", validFieldResultList);
                break;
            }
        }
        logger.info("正在校验参数: " + fullName + "[" + request.getRequestURI() + "]");
        logger.info("请求URL参数: " + (RequestDataUtil.getParameters(request.getParameterMap())));
        if (!beanResult.isPass()) {
            String tips = beanResult.getFieldResultList().get(0).getTips();
            logger.warning(beanResult.getMessage() + "，详情请看: " + beanResult.getFieldResultList());
            logger.info("参数校验不通过: " + fullName);
            EnableValidator enableValidator = arg0.getThis().getClass().getAnnotation(EnableValidator.class);
            ResultType resultType;
            if (enableValidator != null) {
                resultType = enableValidator.resultType();
            } else {
                WebApplicationContext webApplicationContext = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
                ResultConfig resultConfig = webApplicationContext.getBean(ResultConfig.class);
                resultType = resultConfig.getResultType();
            }
            if (resultType == null || resultType == ResultType.THROW_TIPS) {
                throw new ValidatorException("参数校验错误[" + tips + "]");
            }
            this.defaultResult(tips, request, response);
            return null;
        }
        return arg0.proceed();
    }

    /**
     * 默认返回结果
     *
     * @param tips
     * @param request
     * @param response
     */
    private void defaultResult(String tips, HttpServletRequest request, HttpServletResponse response) {
        PrintWriter printWriter = null;
        try {
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/json; charset=utf-8");
            printWriter = response.getWriter();
            String data = "{\"code\":" + ResultCode.BAD.getCode() + ",\"msg\":\"" + tips + "\"}";
            printWriter.write(data);
            this.logger.info(request.getServletPath() + " 的响应内容：" + data);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (printWriter != null) {
                printWriter.close();
            }
        }
    }

}
